package br.org.espmessenger.cliente;

import java.io.FileReader;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import br.org.espmessenger.middleware.ESPMessenger;
import br.org.espmessenger.middleware.InfraEstruturaException;
import br.org.espmessenger.modelo.Usuario;
import br.org.espmessenger.modelo.excecoes.LogonInvalidoException;
import br.org.espmessenger.modelo.excecoes.UsuarioInexistenteException;
import br.org.espmessenger.modelo.excecoes.UsuarioJaCadastradoException;

/**
 * Classe que abstrai a complexidade do subsistema adjacente.
 * Implementa os padrões de projeto:
 * Façade (GoF)
 * Singleton (GoF)
 * Registry (GoF)
 *
 */
public class Fachada {
	private static Fachada instance;
	private Usuario usuario;
    private Map<String, Object> entradas = new HashMap<String, Object>();
	
	// ----------- Métodos do padrão Singleton (construtor privado e getInstance() static)
	private Fachada() throws InfraEstruturaException {
		carregarConfiguracoes();
	}
	public static Fachada getInstance() throws InfraEstruturaException {
		if (instance == null) {
			instance = new Fachada();
		}
		return instance;
	}
	
	// ----------- Métodos do padrão Registry
	public boolean entradaExiste(String chave) {
		return entradas.containsKey(chave);
	}
	public Object getEntrada(String chave) {
		return entradas.get(chave);
	}
	public void setEntrada(String chave, Object valor) {
		entradas.put(chave, valor);
	}

	// ----------- Métodos de negócio
	private void carregarConfiguracoes() throws InfraEstruturaException {
		try {
			FileReader reader = null;
			String caminho = getClass()
			.getResource("/br/org/espmessenger/cliente/cliente.properties")
			.getPath();
			reader = new FileReader(caminho);
			Properties propriedades = new Properties();
			propriedades.load(reader);
			Enumeration<Object> chaves = propriedades.keys();
			while (chaves.hasMoreElements()) {
				String chave = chaves.nextElement().toString();
				String valor = propriedades.getProperty(chave);
				if (!"".equals(valor)) {
					entradas.put(chave, valor);
				}
			}
			reader.close();
		} catch (IOException e) {
			throw new InfraEstruturaException("Falha ao carregar as preferências do cliente", e);
		}
	}
	public void definirServidor(Servidor servidor) {
		setEntrada("servidor.host", servidor.getHost());
		setEntrada("servidor.porta", servidor.getPorta());
		setEntrada("servidor.servico", servidor.getServico());
	}

	public void testarServidor(Servidor servidor) throws InfraEstruturaException {
		AgenteDeInfraEstrutura.testarServidor(servidor);
	}
	public void registrarNovaConta(Usuario usuario) throws InfraEstruturaException, UsuarioJaCadastradoException {
		ESPMessenger messenger = AgenteDeInfraEstrutura.getInstance().getMessenger();
		try {
			messenger.registrarNovaConta(usuario);
		} catch (RemoteException e) {
			throw new InfraEstruturaException("Falha na comunicação com o servidor!", e);
		}
	}
	public Usuario getUsuario() {
		return usuario;
	}
	public void conectarUsuario(Usuario u) throws LogonInvalidoException, InfraEstruturaException {
		ESPMessenger messenger = AgenteDeInfraEstrutura.getInstance().getMessenger();
		try {
			this.usuario = messenger.conectarUsuario(u);
		} catch (RemoteException e) {
			throw new InfraEstruturaException("Falha na comunicação com o servidor!", e);
		}
	}
	public void desconectarUsuario() throws InfraEstruturaException {
		ESPMessenger messenger = AgenteDeInfraEstrutura.getInstance().getMessenger();
		try {
			messenger.desconectarUsuario(usuario);
		} catch (RemoteException e) {
			throw new InfraEstruturaException("Falha na comunicação com o servidor!", e);
		}
	}
	
	
//	
//	// Métodos chamados pela GUI para invocar o modelo de negócio
//	public static void convidar(Usuario convidado, String texto) {
////		usuario.convidar(convidado, texto);
//	}
//	
//	// Métodos chamados de volta pelo modelo
//	public static void enviarConvitePorEmail(MensagemConvite convite) {
//		
//	}
//
//	public static void confirmarReenvioDeConvite(MensagemConvite convite) {
//		// TODO Auto-generated method stub
//		
//	}
//

}
